package org.jeecg.modules.car.web;


import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import io.swagger.annotations.Api;
import io.swagger.models.auth.In;
import lombok.extern.slf4j.Slf4j;
import org.hibernate.validator.constraints.SafeHtml;
import org.jeecg.common.api.vo.ForeignResult;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.api.vo.ShParkingResult;
import org.jeecg.common.util.DateUtils;
import org.jeecg.common.util.MD5Utils;
import org.jeecg.common.util.StringUtils;
import org.jeecg.entity.car.*;
import org.jeecg.enums.PayChannelEnum;
import org.jeecg.enums.PayModeEnum;
import org.jeecg.enums.car.CarOrderTypeEnum;
import org.jeecg.enums.car.CarSyncStatusEnum;
import org.jeecg.modules.car.entity.CarParkInfo;
import org.jeecg.modules.car.service.*;
import org.jeecg.modules.car.service.impl.ForeignCarJGSService;
import org.jeecg.modules.car.service.impl.ForeignCarShParkingService;
import org.jeecg.service.IFeignBaseDataService;
import org.jeecg.vo.car.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

@Slf4j
@Api(tags="上海市公共停车信息平台-对接")
@RestController
@RequestMapping("/b/foreign/sh/parking")
public class ForeignCarShParkingController {

    @Autowired
    private ForeignCarShParkingService foreignCarShParkingService;
    @Autowired
    private ForeignCarJGSService foreignCarJGSService;
    @Autowired
    private ICarParkInfoService carParkInfoService;
    @Autowired
    private ICarParkingRecordService recordService;
    @Autowired
    private ICarOrderService orderService;
    @Autowired
    private ICarUrlConfigService urlConfigService;
    @Autowired
    private ICarModelService modelService;
    @Autowired
    private ICarShOrderService shOrderService;

    /**
     * 查询记录数
     * @param parkId  本系统车场id
     * @return
     */
    @GetMapping(value = "/query")
    public ShParkingResult query(String parkId){
        CarParkInfo carParkInfo = carParkInfoService.getByParkId(parkId);
        if (carParkInfo == null) return ShParkingResult.error("车场不存在");
        return foreignCarShParkingService.query(carParkInfo);
    }

    /**
     * 车辆入场
     * @return
     */
    @PostMapping(value = "/arrive")
    public ShParkingResult arrive(@RequestBody ForeignCarShArriveReq req){
        CarParkInfo carParkInfo = carParkInfoService.getBySuperviseParkId(req.getParkingId());
        if (carParkInfo != null){
            req.setAppId(carParkInfo.getSuperviseAppId());
            req.setPassword(carParkInfo.getSupervisePassword());
        }
        req.setVehicleType(1);
        req.setLaneType(1);
        req.setFreeBerth(100);
        return ShParkingResult.ok(foreignCarShParkingService.arrive(req));
    }

    /**
     * 数据补传
     * @return
     */
    @PostMapping(value = "/resend")
    public ShParkingResult resend(@RequestBody ForeignCarShResendReq resendReq){
        return ShParkingResult.ok(foreignCarShParkingService.resend(resendReq));
    }

    /**
     * 在线停车预约查询 No5.2.1
     * @return
     */
    @PostMapping(value = "/reserves")
    public ShParkingResult reserves(@RequestBody ForeignCarShBase reservesReq){
        CarParkInfo carParkInfo = carParkInfoService.getBySuperviseParkId(reservesReq.getParkingId());
        if (carParkInfo != null){
            reservesReq.setAppId(carParkInfo.getSuperviseAppId());
            reservesReq.setPassword(carParkInfo.getSupervisePassword());
        }
        return ShParkingResult.ok(foreignCarShParkingService.reserves(reservesReq));
    }

    /**
     * 停车缴费减免 No5.3.1
     * @return
     */
    @PostMapping(value = "/reduces")
    public ShParkingResult reduces(String parkId,String plateId){
        CarParkingRecord record =  recordService.getParkingRecordByCarNo(plateId);
        if (record == null) return ShParkingResult.error("无进出记录!");
        CarParkInfo carParkInfo = carParkInfoService.getByParkId(parkId);
        if (carParkInfo == null) return ShParkingResult.error("车场不存在!");
        return ShParkingResult.ok(foreignCarShParkingService.reduces(carParkInfo,plateId,record.getEntranceTime()));
    }


    /**
     * 临停费用信息查询 - 被调 No5.3.2
     * @return
     */
    @PostMapping(value = "/calculatingTempCost")
    public ShParkingResult<ForeignCarShTempCostResp> calculatingTempCost(@RequestBody ForeignCarShTempCostReq tempCostReq){
        CarParkInfo carPark = carParkInfoService.getBySuperviseParkId(tempCostReq.getParkingId());
        if(carPark == null){
            return ShParkingResult.error("车场不存在!");
        }
        CarParkingRecord record = recordService.getParkingRecordByCarNo(tempCostReq.getPlateId());
        if (record == null){
            return ShParkingResult.error("车辆"+tempCostReq.getPlateId() +"无进场记录");
        }
        //TODO 是否有减免
        Result<ForeignCarTempCostResp> resp =  foreignCarJGSService.calculatingTempCost(record.getRecordId(),carPark.getOutSysId(),tempCostReq.getPlateId());
        if ("199".equals(carPark.getId())){  //测试代码
            ForeignCarTempCostResp costResp = new ForeignCarTempCostResp();
            costResp.setRecord_id(record.getRecordId());
            costResp.setTotal_fee("0.01");
            costResp.setUpay_fee("0.01");
            costResp.setDiscount_fee("0");
            costResp.setIn_time(DateUtils.date2Str(record.getEntranceTime(),DateUtils.datetimeFormat));
            costResp.setPlate_number(record.getCarNo());
            costResp.setPark_id(record.getOutParkId());
            resp = Result.ok(costResp);
        }
        if (!resp.isSuccess()){
            return ShParkingResult.error(resp.getMessage());
        }
        BigDecimal totalFee = StringUtils.isNotBlank(resp.getResult().getTotal_fee())? new BigDecimal(resp.getResult().getTotal_fee()): BigDecimal.ZERO;
        BigDecimal uPayFee = StringUtils.isNotBlank(resp.getResult().getUpay_fee())? new BigDecimal(resp.getResult().getUpay_fee()):BigDecimal.ZERO;
        ForeignCarShTempCostResp shTempCostResp = new ForeignCarShTempCostResp();
        String sn = foreignCarShParkingService.getSeq(tempCostReq.getParkingId());
        shTempCostResp.setParkingId(tempCostReq.getParkingId());
        shTempCostResp.setPlateId(tempCostReq.getPlateId());
        shTempCostResp.setVehicleType(tempCostReq.getVehicleType());
        shTempCostResp.setBussinessId(record.getRecordId());
        shTempCostResp.setOrderId(sn);
        Calendar arrived = Calendar.getInstance();
        arrived.setTime(record.getEntranceTime());
        shTempCostResp.setArrivedTime(arrived.getTimeInMillis());
        shTempCostResp.setTotalMoney(totalFee.multiply(new BigDecimal(100)).intValue());
        shTempCostResp.setDueMoney(uPayFee.multiply(new BigDecimal(100)).intValue());
        if (shTempCostResp.getDueMoney() <= 0){
            return ShParkingResult.error("未产生费用");
        }
        shTempCostResp.setReduceMoney(0);
        shTempCostResp.setReduceTime(0);
        shTempCostResp.setReduceCode("99999");
        shTempCostResp.setValidityQuoteTime(15*60*1000L);
        shTempCostResp.setRemark(tempCostReq.getPlateId());
        shTempCostResp.setDataTime(System.currentTimeMillis());
        //创建临停缴费订单
        CarOrder carOrder = new CarOrder();
        carOrder.setOrderNo(resp.getResult().getOrder_no());
        carOrder.setId(String.valueOf(IdWorker.getId()));
        carOrder.setTenantId(carPark.getTenantId());
        carOrder.setProjectId(carPark.getProjectId());
        carOrder.setPayMode(PayModeEnum.PAY_MODE_APP.getCode());
        carOrder.setCarTypeName("临停车");
        carOrder.setOrderType(CarOrderTypeEnum.ORDER_TYPE_TEMP.getCode());
        carOrder.setSyncStatus(CarSyncStatusEnum.SYNC_STATUS_NO.getCode());
        carOrder.setCheckStatus(1);
        carOrder.setPayAmount(uPayFee);
        carOrder.setPayDue(totalFee);
        carOrder.setPayReduced(BigDecimal.ZERO);
        carOrder.setSn(sn);
        carOrder.setRecordId(record.getRecordId());
        carOrder.setCarNo(tempCostReq.getPlateId());
        carOrder.setParkId(carPark.getId());
        carOrder.setPayChannel(PayChannelEnum.PAY_CHANNEL_SH.getCode());
        log.info("临停缴费插入的订单信息:{}",carOrder);
        orderService.save(carOrder);
        return ShParkingResult.ok(shTempCostResp);
    }


    /**
     * 停车缴费信息上传 No5.3.3
     * @return
     */
    @PostMapping(value = "/payment")
    public ForeignResult payment(@RequestBody ForeignCarShPaymentReq paymentReq){
        CarParkInfo carParkInfo = carParkInfoService.getBySuperviseParkId(paymentReq.getParkingId());
        if (carParkInfo != null){
            paymentReq.setAppId(carParkInfo.getSuperviseAppId());
            paymentReq.setPassword(carParkInfo.getSupervisePassword());
        }
        return ForeignResult.ok(foreignCarShParkingService.payment(paymentReq));
    }

    /**
     * 平台支付成功后回调 No5.3.4
     * @return
     */
    @PostMapping(value = "/payCallback")
    public ForeignResult payCallback(@RequestBody ForeignCarShPayCallBackReq payCallBackReq){
        log.info("公共平台回调接口参数：{}",payCallBackReq);
        return orderService.carPayNotifySH(payCallBackReq);
    }

    /**
     * 平台支付结果查询 No5.3.5
     * @return
     */
    @PostMapping(value = "/payResult")
    public ShParkingResult payResult(String orderId){
        CarOrder carOrder = orderService.getOrderBySn(orderId);
        if (carOrder == null) return ShParkingResult.error("订单号不存在!");
        ForeignCarShPayResultReq payResultReq = new ForeignCarShPayResultReq();
        CarParkInfo carParkInfo = carParkInfoService.getByParkId(carOrder.getParkId());
        if (carParkInfo == null) return ShParkingResult.error("车场不存在!");
        if (StringUtils.isBlank(carParkInfo.getSuperviseAppId()) || StringUtils.isBlank(carParkInfo.getSupervisePassword())){
            return ShParkingResult.error("车场未配置公共平台必要参数!");
        }
        if (carParkInfo != null){
            payResultReq.setAppId(carParkInfo.getSuperviseAppId());
            payResultReq.setPassword(carParkInfo.getSupervisePassword());
        }
        payResultReq.setBusinessId(carOrder.getRecordId());
        payResultReq.setOrderId(orderId);
        payResultReq.setParkingId(carParkInfo.getSuperviseParkingId());
        JSONObject jsonObject =  foreignCarShParkingService.payResult(payResultReq);
        String code = jsonObject.getString("code");
        if ("0".equals(code)){
            JSONObject data = jsonObject.getJSONObject("data");
            ForeignCarShPayResultsResp resp = data.toJavaObject(ForeignCarShPayResultsResp.class);
            return ShParkingResult.ok(resp);
        }
        return ShParkingResult.error(jsonObject.getString("message"));
    }

    /**
     * 停车缴费对账单下载 No5.3.6
     * @param parkId 本系统的车场id
     * @param payDate
     * @return
     */
    @PostMapping(value = "/payResults")
    public ShParkingResult payResults(String parkId, @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") Date payDate){
        CarParkInfo carParkInfo = carParkInfoService.getByParkId(parkId);
        if (carParkInfo == null) return ShParkingResult.error("车场不存在!");
        if (StringUtils.isBlank(carParkInfo.getSuperviseAppId()) || StringUtils.isBlank(carParkInfo.getSupervisePassword())){
            return ShParkingResult.error("车场未配置公共平台必要参数!");
        }
        ForeignCarShPayResultsReq payResultsReq = new ForeignCarShPayResultsReq();
        payResultsReq.setParkingId(carParkInfo.getSuperviseParkingId());
        payResultsReq.setAppId(carParkInfo.getSuperviseAppId());
        payResultsReq.setPassword(carParkInfo.getSupervisePassword());
        payResultsReq.setPayDate(payDate.getTime());
        JSONObject jsonObject = foreignCarShParkingService.payResults(payResultsReq);
        String code = jsonObject.getString("code");
        if ("0".equals(code)){
            JSONArray data = jsonObject.getJSONArray("data");
            List<ForeignCarShPayResultsResp> payResultsList = data.toJavaList(ForeignCarShPayResultsResp.class);
            if (payResultsList == null) return ShParkingResult.ok(data);
            List<CarShOrder> shOrderList = new ArrayList<>();
            for (ForeignCarShPayResultsResp resp:payResultsList){
                CarShOrder shOrder = new CarShOrder();
                shOrder.setId(IdWorker.getIdStr());
                shOrder.setTenantId(carParkInfo.getTenantId());
                shOrder.setProjectId(carParkInfo.getProjectId());
                shOrder.setParkId(carParkInfo.getId());
                Calendar ca = Calendar.getInstance();
                ca.setTimeInMillis(resp.getPayTime());
                shOrder.setPayTime(ca.getTime());
                shOrder.setPayType(resp.getPayType());
                shOrder.setSn(resp.getOrderId());
                BigDecimal payAmount = resp.getPayMoney() == null ? BigDecimal.ZERO: new BigDecimal(resp.getPayMoney());
                payAmount = payAmount.divide(new BigDecimal(100),2,BigDecimal.ROUND_HALF_UP);
                shOrder.setPayAmount(payAmount);
                shOrder.setCreateTime(new Date());
                shOrder.setUpdateTime(new Date());
                shOrderList.add(shOrder);
            }
            if (shOrderList.size() > 0){
                shOrderService.batchSaveOrUpdate(shOrderList);
            }
            return ShParkingResult.ok(payResultsList);
        }
        return ShParkingResult.error(jsonObject.getString("message"));
    }


    /**
     *  发票开具请求 No5.3.7
     * @return
     */
    @PostMapping(value = "/invoice")
    public ShParkingResult invoice(@RequestBody ForeignCarShSearchPlateReq invoiceReq){
        log.info("发票开具请求接受参数:invoiceReq:{}",invoiceReq);
        CarParkInfo carParkInfo = carParkInfoService.getBySuperviseParkId(invoiceReq.getParkingId());
        if (carParkInfo == null) return ShParkingResult.error("车场不存在!");
        CarParkingRecord carParkingRecord = recordService.getParkingRecordByCarNo(invoiceReq.getPlateId());
        if (carParkingRecord == null) return ShParkingResult.error("车辆不在场!");
        // TODO  payType问题 既然是非市平台支付 payType怎么传？

        return ShParkingResult.error("");
    }



    /**
     *  场内寻车 No5.3.8
     * @return
     */
    @PostMapping(value = "/searchPlate")
    public ShParkingResult searchPlate(@RequestBody ForeignCarShSearchPlateReq searchPlateReq){
        log.info("场内寻车接受参数:searchPlateReq:{}",searchPlateReq);
        CarParkInfo carParkInfo = carParkInfoService.getBySuperviseParkId(searchPlateReq.getParkingId());
        if (carParkInfo == null) return ShParkingResult.error("车场不存在!");
        CarParkingRecord carParkingRecord = recordService.getParkingRecordByCarNo(searchPlateReq.getPlateId());
        if (carParkingRecord == null) return ShParkingResult.error("车辆不在场!");
        ForeignCarShSearchPlateResp searchPlateResp = new ForeignCarShSearchPlateResp();
        searchPlateResp.setParkingId(searchPlateReq.getParkingId());
        searchPlateResp.setBussinessId(carParkingRecord.getRecordId());
        CarModel carModel = modelService.getByModelId(carParkingRecord.getCarModel());
        searchPlateResp.setVehicleType(1);
        if (carModel != null){
           if(carModel.getName().contains("大")){
               searchPlateResp.setVehicleType(2);
           }
        }
        searchPlateResp.setPlateId(searchPlateReq.getPlateId());
        searchPlateResp.setParkingFloor(1);
        searchPlateResp.setParkingStore(carParkInfo.getParkName());
        searchPlateResp.setDataTime(System.currentTimeMillis());
        return ShParkingResult.ok(searchPlateResp);
    }


    /**
     *  停车票据下载 No5.3.9
     * @return
     */
    @PostMapping(value = "/billinfos")
    public ShParkingResult billInfos(String parkId,@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") Date billDate){
        CarParkInfo carParkInfo = carParkInfoService.getByParkId(parkId);
        if (carParkInfo == null) return ShParkingResult.error("车场不存在!");
        ForeignCarShPayResultsReq payResultsReq = new ForeignCarShPayResultsReq();
        payResultsReq.setParkingId(carParkInfo.getSuperviseParkingId());
        payResultsReq.setAppId(carParkInfo.getSuperviseAppId());
        payResultsReq.setPassword(carParkInfo.getSupervisePassword());
        payResultsReq.setPayDate(billDate.getTime());
        JSONObject jsonObject = foreignCarShParkingService.billInfos(payResultsReq);
        String code = jsonObject.getString("code");
        if ("0".equals(code)){
            JSONArray data = jsonObject.getJSONArray("data");
            List<ForeignCarShPayResultsResp> payResultsList = data.toJavaList(ForeignCarShPayResultsResp.class);
            if (payResultsList == null) return ShParkingResult.ok(data);
            //todo -- 保存数据库
            return ShParkingResult.ok(payResultsList);
        }
        return ShParkingResult.error(jsonObject.getString("message"));
    }

    /**
     *  通知路径注册 No5.3.10
     * @param parkId 本系统的车场id
     * @param urlType url类型  1:停车缴费信息查询接口路径
     *                        2:支付成功记录通知接口
     *                        3:发票开具请求查询路径
     *                        4:场内寻车接口
     * @return
     */
    @PostMapping(value = "/pathUrl")
    public ShParkingResult pathUrl(String parkId, Integer urlType){
        CarParkInfo carParkInfo = carParkInfoService.getByParkId(parkId);
        if (carParkInfo == null) return ShParkingResult.error("车场不存在!");
        if (StringUtils.isBlank(carParkInfo.getSuperviseAppId()) || StringUtils.isBlank(carParkInfo.getSupervisePassword())){
            return ShParkingResult.error("车场未配置公共平台必要参数!");
        }
        CarUrlConfig urlConfig = urlConfigService.getByUrlType(parkId,urlType);
        if (urlConfig == null) return ShParkingResult.error("车场未配置相关的url");
        ForeignCarShPathUrlReq pathUrlReq = new ForeignCarShPathUrlReq();
        if (carParkInfo != null){
            pathUrlReq.setAppId(carParkInfo.getSuperviseAppId());
            pathUrlReq.setPassword(carParkInfo.getSupervisePassword());
            pathUrlReq.setParkingId(carParkInfo.getSuperviseParkingId());
        }
        pathUrlReq.setLeftValidTime(urlConfig.getLeftValidTime());
        pathUrlReq.setUrl(urlConfig.getUrl());
        pathUrlReq.setUrlType(urlConfig.getUrlType());
        JSONObject jsonObject = foreignCarShParkingService.pathUrl(pathUrlReq);
        String code = jsonObject.getString("code");
        if ("0".equals(code)){
            urlConfigService.updateSyncStatus(urlConfig.getId(),true);
            return ShParkingResult.ok();
        }
        return ShParkingResult.error(jsonObject.getString("message"));
    }

    /**
     * 配置参数查询 No5.3.11
     * @param parkId 本系统的车场id
     * @return
     */
    @PostMapping(value = "/params")
    public ShParkingResult params(String parkId){
        CarParkInfo carParkInfo = carParkInfoService.getByParkId(parkId);
        if (carParkInfo == null) return ShParkingResult.error("车场不存在!");
        if (StringUtils.isBlank(carParkInfo.getSuperviseAppId()) || StringUtils.isBlank(carParkInfo.getSupervisePassword())){
            return ShParkingResult.error("车场未配置公共平台必要参数!");
        }
        ForeignCarShBase baseReq = new ForeignCarShBase();
        if (carParkInfo != null){
            baseReq.setAppId(carParkInfo.getSuperviseAppId());
            baseReq.setPassword(carParkInfo.getSupervisePassword());
            baseReq.setParkingId(carParkInfo.getSuperviseParkingId());
        }
        JSONObject jsonObject = foreignCarShParkingService.params(baseReq);
        String code = jsonObject.getString("code");
        if ("0".equals(code)){
            return ShParkingResult.ok(jsonObject.getString("message"));
        }
        return ShParkingResult.error(jsonObject.getString("message"));
    }



    /**
     * 测试数据签名
     * @return
     */
//    @PostMapping(value = "/testSign")
    public static ForeignResult testSign(){
        String str = "12345678909876543|{\"parkingId\":\"qp31022900183\",\"plateId\":\"皖AP1851\",\"dataTime\":1507863248063}";
        System.out.println(str);
        String str2 = MD5Utils.getMd5(str).toLowerCase();
        System.out.println(str2);
        return ForeignResult.ok(str);
    }

}
